package com.csthink.web.infrastructure.security.authorization.decider;

import com.csthink.common.infrastructure.enums.Authorities;
import com.csthink.web.infrastructure.security.AuthenticationInfoUtil;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

/**
 * 授权校验类
 * 使用方式: @PreAuthorize("@decider.allowUserEdit()")
 *
 * @author <a href="mailto:security.2009@live.cn">Mars</a>
 * @since 2023-09-13
 */
@Component("decider")
public class DefaultAuthorizationDecider {
    public boolean allowRead(Authorities authorities) {
        if (allowEdit(authorities)) {
            return true;
        }

        Set<String> authoritySet = getAuthoritySet();
        String read = authorities.readValue();
        return StringUtils.isNotBlank(read) && authoritySet.contains(read);
    }

    public boolean allowEdit(Authorities authorities) {
        Set<String> authoritySet = getAuthoritySet();
        String edit = authorities.editValue();
        return StringUtils.isNotBlank(edit) && authoritySet.contains(edit);
    }

    /**
     * 获取当前登录用户的所有权限
     *
     * @return
     */
    protected Set<String> getAuthoritySet() {
        Collection<? extends GrantedAuthority> userAuthorities = AuthenticationInfoUtil.getAuthentication().getAuthorities();
        if (CollectionUtils.isEmpty(userAuthorities)) {
            return Collections.emptySet();
        }

        return AuthorityUtils.authorityListToSet(userAuthorities);
    }

    public boolean allowUserEdit() {
        return allowEdit(Authorities.CST_USER);
    }

    public boolean allowUserRead() {
        return allowRead(Authorities.CST_USER);
    }

    public boolean allowInboxEdit() {
        return allowEdit(Authorities.CST_INBOX);
    }

    public boolean allowInboxRead() {
        return allowRead(Authorities.CST_INBOX);
    }

    // 权限都需要自定义 allowXXXEdit() & allowXXXRead() 方法
}
